#include <iostream>
#include <cstring>
#include <string>
#include "nocopy.hpp" //禁止拷贝
#include "Log.hpp"
#include "myThread.hpp"
using namespace ThreadMoudle;

// OS
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

void ClientSender(int sockfd, struct sockaddr_in server_socket, int len)
{
    while (1)
    {
        // 读取键盘 + 发送
        std::string str;
        std::getline(std::cin, str);
        int n = sendto(sockfd, str.c_str(), str.size(), 0, (struct sockaddr *)&server_socket, len);
        if (n >= 0)
        {
            LOG(INFO, "client sento success");
        }
        else
        {
            LOG(FATAL, "client sento fail");
            exit(-1);
        }
    }
}
void ClientServer(int sockfd)
{
    while (1)
    {
        // 接收
        sockaddr_in ser_socket; // 虽然不用，但可以用来占位防止出错，比nullptr好
        uint len = sizeof(ser_socket);
        std::string buff_str;
        buff_str.resize(1024); // 扩容
        int re = recvfrom(sockfd, &buff_str[0], buff_str.size(), 0, (struct sockaddr *)&ser_socket, &len);
        // recvfrom(sockfd, (void*)buff_str.data(), buff_str.size(), 0, (struct sockaddr*)&ser_socket, &len);
        if (re >= 0)
        {
            Log(INFO, "recvfrom success");
            buff_str[re] = '\0'; // 末尾加0
            std::cout << "server return sendto:" << buff_str << std::endl;
            std::cerr << "server return sendto:" << buff_str << std::endl;
        }
        else
        {
            Log(FATAL, "client recvfrom fail");
            exit(-1);
        }
    }
}

//./client serverip serverport
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        std::cout << "Usage: ./xxx serverip serverport" << std::endl;
        exit(-1);
    }
    std::string ser_ip = argv[1];
    uint16_t ser_port = std::stoi(argv[2]);

    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        Log(FATAL, "socket fail");
        exit(-1);
    }

    // OS会自动填充+bind client的socket

    // 填充目标server_socket    发消息用
    struct sockaddr_in server_socket;
    uint len = sizeof(server_socket);
    bzero(&server_socket, len);         // 初始化
    server_socket.sin_family = AF_INET; // ipv4网络地址族
    server_socket.sin_port = htons(ser_port);
    // server_socket.sin_addr.s_addr =  //随便发

    // 两个线程，一个专门收，一个专门发；解决了之前不发就不读的问题
    func_t C_Sender = std::bind(ClientSender, sockfd, server_socket, len);
    func_t C_Server = std::bind(ClientServer, sockfd);
    myThread mt_sender("clent_sender", C_Sender);
    myThread mt_server("clent_server", C_Server);

    mt_sender.Start();
    mt_server.Start();

    mt_sender.Join();
    mt_server.Join();


    // while (1)
    // {
    //     // 读取键盘 + 发送
    //     std::string str;
    //     std::getline(std::cin, str);
    //     int n = sendto(sockfd, str.c_str(), str.size(), 0, (struct sockaddr *)&server_socket, len);
    //     if (n >= 0)
    //     {
    //         // 接收
    //         sockaddr_in ser_socket; // 虽然不用，但可以用来占位防止出错，比nullptr好
    //         uint len = sizeof(ser_socket);
    //         std::string buff_str;
    //         buff_str.resize(1024); // 扩容
    //         int re = recvfrom(sockfd, &buff_str[0], buff_str.size(), 0, (struct sockaddr *)&ser_socket, &len);
    //         // recvfrom(sockfd, (void*)buff_str.data(), buff_str.size(), 0, (struct sockaddr*)&ser_socket, &len);
    //         if (re >= 0)
    //         {
    //             Log(INFO, "recvfrom success");
    //             buff_str[re] = '\0'; // 末尾加0
    //             std::cout << "server return sendto:" << buff_str << std::endl;
    //         }
    //         else
    //         {
    //             Log(FATAL, "recvfrom fail");
    //             break;
    //         }
    //     }
    //     else //(n < 0) // 比//n == -1 增加了健壮性/鲁棒性
    //     {
    //         Log(FATAL, "sendto fail");
    //         // exit(-1);
    //         break;
    //     }
    //}

    close(sockfd);

    return 0;
}